package crazyjava;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
       //java5新线程知识总结
       //1.新的线程池产生方式，可以参考数据库连接池
    	ExecutorService threadPool = Executors.newCachedThreadPool();//无固定数量的线程池，无上限，根据需要产生
    	ExecutorService threadPoo2 = Executors.newFixedThreadPool(3);//产生固定数量的线程，只有当一个线程完成后，在开启新的线程
    	ExecutorService threadPoo3 = Executors.newSingleThreadExecutor();//只有一个线程
    	threadPool.execute(new Runnable() {
			public void run() {
			}
		});//添加线程任务的方式
    	threadPoo2.shutdown();//线程全部运行结束后在全部释放线程
    	threadPoo3.shutdownNow();//无论是否线程全部结束，运行到此释放全部线程
    	//2.创建带有返回值的线程
    	/*
    	 * Future取得的结果类型和Callable返回的结果类型必须一致，这是通过泛型来实现的。
         * Callable要采用ExecutorSevice的submit方法提交，返回的future对象可以取消任务。
         * CompletionService用于提交一组Callable任务，其take方法返回已完成的一个Callable任务对应的Future对象。
    	 * */
    	Future<String> out = threadPool.submit(new Callable<String>() {
			public String call() throws Exception {
				return null;
			}
		});
    	CompletionService<String> outputs = new ExecutorCompletionService<String>(threadPool);
    	for(int i=0;i<10;i++){
    		outputs.submit(new Callable<String>() {
				public String call() throws Exception {
					return null;
				}
			});
    	}
    	for(int i=0;i<10;i++){
    		try {
				outputs.take().get();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
    	}
    	//3.定时触发线程执行
    	ScheduledExecutorService ses = Executors.newScheduledThreadPool(3);
    	ScheduledFuture sf= ses.scheduleWithFixedDelay(new Runnable() {
			public void run() {
			}
		}, 1000, 1000, TimeUnit.SECONDS);
    	sf.cancel(true);//取消定时执行的任务
        //4.先的线程锁
    	/*
    	 * Lock比传统线程模型中的synchronized方式更加面向对象，与生活中的锁类似，锁本身也应该是一个对象。两个线程执行的代码片段要实现同步互斥的效果，它们必须用同一个Lock对象。
                                      读写锁：分为读锁和写锁，多个读锁不互斥，读锁与写锁互斥，这是由jvm自己控制的，你只要上好相应的锁即可。如果你的代码只读数据，可以很多人同时读，但不能同时写，那就上读锁；如果你的代码修改数据，只能有一个人在写，且不能同时读取，那就上写锁。总之，读的时候上读锁，写的时候上写锁！
                                      在等待 Condition 时，允许发生“虚假唤醒”，这通常作为对基础平台语义的让步。对于大多数应用程序，这带来的实际影响很小，因为 Condition 应该总是在一个循环中被等待，并测试正被等待的状态声明。某个实现可以随意移除可能的虚假唤醒，但建议应用程序程序员总是假定这些虚假唤醒可能发生，因此总是在一个循环中等待。
                                       一个锁内部可以有多个Condition，即有多路等待和通知，可以参看jdk1.5提供的Lock与Condition实现的可阻塞队列的应用案例，从中除了要体味算法，还要体味面向对象的封装。在传统的线程机制中一个监视器对象上只能有一路等待和通知，要想实现多路等待和通知，必须嵌套使用多个同步监视器对象。（如果只用一个Condition，两个放的都在等，一旦一个放的进去了，那么它通知可能会导致另一个放接着往下走。）
    	 * */
    	
    }
}
